package cn.tq365.service.google;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javax.annotation.Resource;

import org.apache.ibatis.executor.BatchExecutor;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;

import cn.tq365.mapper.ChannelAccountMapper;
import cn.tq365.model.channel.struct.ChannelAccount;
import cn.tq365.model.struct.google.GoogleAccount;
import cn.tq365.service.channel.ChannelAccountService;
import cn.tq365.util.google.SyncGoogleUtil;
import cn.tq365.util.mybatis.SqlSessionFactoryUtil;

import com.google.api.adwords.lib.AdWordsService;
import com.google.api.adwords.lib.AdWordsUser;
import com.google.api.adwords.v201109.mcm.Account;
import com.google.api.adwords.v201109.mcm.Link;
import com.google.api.adwords.v201109.mcm.ServicedAccountGraph;
import com.google.api.adwords.v201109.mcm.ServicedAccountSelector;
import com.google.api.adwords.v201109.mcm.ServicedAccountServiceInterface;

/**
 * 谷歌账户服务类
 * 
 * @author lili
 * 
 */
@Service
@Scope("prototype")
public class GoogleAccountService implements ChannelAccountService {
	@Resource
	ChannelAccountMapper googleAccountMapper;
	@Resource
	SqlSessionFactoryUtil sqlSessionFactoryUtil;

	@Override
	public void addAll() throws Exception {
		ExecutorService exe = Executors.newFixedThreadPool(3);
		List<AdWordsUser> users = SyncGoogleUtil.getAdWordsUsers();
		for (final AdWordsUser user : users) {
			exe.execute(new Runnable() {
				@Override
				public void run() {
					ServicedAccountGraph graph = null;
					boolean flag = true;
					int max = 1;
					List<GoogleAccount> accList = new ArrayList<GoogleAccount>();
					while (flag) {
						try {
							ServicedAccountServiceInterface servicedAccountService = user
									.getService(AdWordsService.V201109.SERVICED_ACCOUNT_SERVICE);
							ServicedAccountSelector selector = new ServicedAccountSelector();
							selector.setEnablePaging(false);
							selector.setSubmanagersOnly(false);
							graph = servicedAccountService.get(selector);
							if (graph != null) {
								Map<Long, GoogleAccount> customerIdToAccountNode = new HashMap<Long, GoogleAccount>();
								GoogleAccount node = null;
								for (Account account : graph.getAccounts()) {
									node = new GoogleAccount();
									node.setCode(account.getCustomerId());
									node.setEmail(account.getLogin());
									node.setCompany(account.getCompanyName());
									node.setType(account.getCanManageClients() ? 1
											: 0);
									customerIdToAccountNode.put(
											account.getCustomerId(), node);
								}

								if (graph.getLinks() != null) {
									for (Link link : graph.getLinks()) {
										node = customerIdToAccountNode.get(link
												.getClientId().getId());
										node.setParentCode(link.getManagerId()
												.getId());
										node.setName(link.getDescriptiveName());
									}
								}
								Iterator<Map.Entry<Long, GoogleAccount>> it = customerIdToAccountNode
										.entrySet().iterator();

								while (it.hasNext()) {
									Map.Entry<Long, GoogleAccount> entry = (Entry<Long, GoogleAccount>) it
											.next();
									node = entry.getValue();
									accList.add(node);
								}
							}
							flag = false;
							batchAdd(accList);
						} catch (Exception e) {
							e.printStackTrace();
							if (max++ < 7) {
								continue;
							} else {
								flag = false;
							}

						}
					}
				}
			});
		}
		exe.shutdown();
	}

	@Override
	public void add(ChannelAccount account) throws Exception {
	}

	/**
	 * 批量入库
	 * 
	 * @param accList
	 * @throws Exception
	 */
	private void batchAdd(List<GoogleAccount> accList) throws Exception {
		SqlSession session = null;
		BatchExecutor be = null;
		try {
			SqlSessionFactory sqlSessionFactory = sqlSessionFactoryUtil
					.getSqlSessionFactory();
			session = sqlSessionFactory.openSession(ExecutorType.BATCH, false);
			long bt = System.currentTimeMillis();
			for (GoogleAccount account : accList) {
				session.insert("cn.tq365.mapper.GoogleAccountMapper.add",
						account);
			}
			System.out.println(System.currentTimeMillis() - bt);
			session.commit();
		} catch (Exception e) {
			e.printStackTrace();
			session.rollback();
			throw e;
		} finally {
			session.close();
		}
	}
}
